use winapi::um::psapi::{EnumProcesses, GetProcessImageFileNameW};
use winapi::um::winnt::{HANDLE, PROCESS_QUERY_INFORMATION};
use winapi::um::handleapi::CloseHandle;
use winapi::um::processthreadsapi::OpenProcess;
use std::mem;
use std::ptr;
use std::ffi::OsString;
use std::os::windows::ffi::OsStringExt;
use std::path::PathBuf;

pub fn get_processes_by_name(name: &str) -> Vec<u32> {
    let mut process_ids: [u32; 1024] = [0; 1024];
    let mut bytes_returned: u32 = 0;

    unsafe {
        EnumProcesses(process_ids.as_mut_ptr(), mem::size_of::<[u32; 1024]>() as u32, &mut bytes_returned);
    }

    let num_processes = bytes_returned / 4;
    let mut result = Vec::new();

    for i in 0..num_processes {
        let process_id = process_ids[i as usize];
        let handle: HANDLE = unsafe { OpenProcess(PROCESS_QUERY_INFORMATION, 0, process_id) };
        if handle != ptr::null_mut() {
            let mut buffer: [u16; 1024] = [0; 1024];
            let size = (mem::size_of::<[u16; 1024]>() * 2) as u32;
            let results = unsafe { GetProcessImageFileNameW(handle, buffer.as_mut_ptr(), size) };
            if results > 0 {
                let os_string = OsString::from_wide(&buffer[..(results as usize)]);
                let path_buf = PathBuf::from(&os_string);
                if let Some(file_name) = path_buf.file_name() {
                    if let Some(name_str) = file_name.to_str() {
                        if name_str.to_lowercase().contains(&name.to_lowercase()) {
                            let found_process_id = process_id;
                            result.push(found_process_id);
                        }
                    }
                }
            }
            unsafe { CloseHandle(handle) };
        }
    }

    result
}